package com.xcity.game.activity.charm;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import com.xcity.db.entity.Config;
import com.xcity.db.entity.Player;
import com.xcity.db.entity.Ranking;
import com.xcity.db.mapper.ConfigMapper;
import com.xcity.game.activity.ActivityService;
import com.xcity.game.common.Cause;
import com.xcity.game.common.ItemResponse;
import com.xcity.game.common.MessageConst;
import com.xcity.game.common.PlayerPool;
import com.xcity.game.item.DropGroupTemplate;
import com.xcity.game.item.drop.Drop;
import com.xcity.game.item.drop.DropGroup;
import com.xcity.game.item.drop.listener.ItemDropListener;
import com.xcity.game.mail.MailAttach;
import com.xcity.game.mail.MailService;
import com.xcity.game.player.cache.PlayerCacheService;
import com.xcity.game.rank.RankingListEnum;
import com.xcity.pomelo.PomeloRoute;
import com.xcity.pomelo.request.ActivityCharmTopCongratulationRequest;
import com.xcity.pomelo.request.ActivityCharmTopInfoRequest;
import com.xcity.pomelo.response.ActivityCharmTopCongratulationResponse;
import com.xcity.pomelo.response.ActivityCharmTopInfoResponse;
import com.xcity.pomelo.response.HintResponse;
import com.xcity.pomelo.response.Response;
import com.xcity.util.DBUtils;

import naga.x.App;
import naga.x.game.template.TemplateService;
import naga.x.game.time.DayListener;
import naga.x.game.time.TimeUpdater;
import naga.x.net.Session;
import naga.x.net.annotation.OPHandler;
import naga.x.net.impl.pomelo.annotation.PomeloOP;
import naga.x.service.ServiceException;
import naga.x.util.NumberUtils;
import naga.x.util.TimeUtils;

/**
 * 魅力周榜活动
 * @author yang.li
 *
 */
@OPHandler
public class CharmTopActivityService extends ActivityService implements DayListener {

//	private ActorService actorService;
//	private RankingService rankingService;
	private PlayerCacheService playerCacheService;
	private long topPlayerId;
	
	/** 每天最多祝贺次数 */
	public static final int MAX_CONGRATULATION_TIMES_PER_DAY = 1;
//	/** 每周1零点更新第一名 */
//	private static final int DAY_OF_WEEK_UPDATE_TOP_PLAYER = 0;
	/** 每天8点更新玩家祝贺次数 */
	private static long updateCongratulationNumTime = TimeUtils.getTodayZeroTime() + TimeUnit.HOURS.toMillis(8);
	/** 祝贺奖励掉落组id */
	private static final int CONGRATULATION_REWARD_DROP_GROUP_ID = 110005;
	private DropGroup congratulationRewardDropGroup;
	/** 第一名玩家奖励钻石 */
	private static final int TOP_PLAYER_REWARD_STONE = 30;
	
	public static class RewardDropListener implements ItemDropListener {
		private List<ItemResponse> items;
		@Override
		public void itemDroped(Player player, int itemId, int count) {
			if (items == null)
				items = new ArrayList<ItemResponse>(2);
			items.add(new ItemResponse(itemId, count));
		}
		public List<ItemResponse> getItems() {
			return items;
		}
	}
	
	@Override
	public void startup() throws ServiceException {
		playerCacheService = Objects.requireNonNull(App.getApp().getServiceManager().get(PlayerCacheService.class));
		Config cfg = DBUtils.find(Config.KEY_CHARM_TOP_WEEK, ConfigMapper.class);
		if (cfg != null) {
			topPlayerId = NumberUtils.parseLong(cfg.getValue());
		} else {
			reloadTopPlayer();
			DBUtils.save(new Config(Config.KEY_CHARM_TOP_WEEK, String.valueOf(topPlayerId)), ConfigMapper.class);
		}
		TimeUpdater.getInstance().addDayListener(this);
	}

	@Override
	public void shutdown() throws ServiceException {
		DBUtils.update(new Config(Config.KEY_CHARM_TOP_WEEK, String.valueOf(topPlayerId)), ConfigMapper.class);
	}

	@Override
	public boolean dayChanged() {
		updateCongratulationNumTime = TimeUtils.getTodayZeroTime() + TimeUnit.HOURS.toMillis(8);
		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(TimeUpdater.getInstance().now());
		if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
			// 每周一零点
			long previousPlayerId = reloadTopPlayer();
			if (previousPlayerId != 0L) {
				MailAttach attach = new MailAttach(0, TOP_PLAYER_REWARD_STONE);
				App.getApp().getServiceManager().get(MailService.class).sendSystemMail(previousPlayerId,
						MessageConst.ACTIVITY_CHARM_TOP_PRIZE_MAIL_TITLE,
						MessageConst.ACTIVITY_CHARM_TOP_PRIZE_MAIL_CONTENT,
						attach);
				LOG.info("[ACTCHARMTOP TOP1REWARD]ID[{}]", previousPlayerId);
			}
		}
		return true;
	}
	
	@PomeloOP(PomeloRoute.ACTIVITY_CHARM_TOP_INFO)
	protected void requestInfo(Session session, ActivityCharmTopInfoRequest req) {
		Player player = session.getClient();
		Response res = new ActivityCharmTopInfoResponse(req.getSerial(), getTopPlayer(), getLeftCongratulationTimes(player));
		session.send(res);
	}
	
	@PomeloOP(PomeloRoute.ACTIVITY_CHARM_TOP_PLAYER_CONGRATULATION)
	protected void requestCongratulation(Session session, ActivityCharmTopCongratulationRequest req) {
		if (topPlayerId == 0) {
			session.send(new HintResponse(req.getSerial(), MessageConst.ACTIVITY_CHARM_TOP_NO_PLAYER));
			return;
		}
		Player player = session.getClient();
		if (player.getId() == topPlayerId) {
			session.send(new HintResponse(req.getSerial(), MessageConst.ACTIVITY_CHARM_TOP_CAN_NOT_CONGRATULATE_SELF));
			return;
		}
		if (getLeftCongratulationTimes(player) <= 0) {
			session.send(new HintResponse(req.getSerial(), MessageConst.ACTIVITY_CHARM_TOP_CONGRATULATED));
			return;
		}
		addCongratulationTimes(player);
		DropGroup drop = getCongratulationRewardDropGroup();
		RewardDropListener listener = new RewardDropListener();
		drop.drop(Drop.RND, player, Cause.ACTIVITY_CHARMTOP, listener);
		Response res = new ActivityCharmTopCongratulationResponse(req.getSerial(), listener.getItems(), getLeftCongratulationTimes(player));
		session.send(res);
		LOG.info("[ACTCHARMTOP]ID[{}]TARGET[{}]", player.getId(), topPlayerId);
	}
	
//	private ActorService getActorService() {
//		return actorService != null ? actorService : (actorService = App.getApp().getServiceManager().get(ActorService.class));
//	}
	
//	private RankingService getRankingService() {
//		return rankingService != null ? rankingService : (rankingService = App.getApp().getServiceManager().get(RankingService.class));
//	}
	
	public Player getTopPlayer() {
//		return topPlayerId != 0 ? getActorService().find(topPlayerId) : null;
		return topPlayerId != 0 ? playerCacheService.find(topPlayerId) : null;
	}
	
	private long reloadTopPlayer() {
		long old = topPlayerId;
		Ranking top = RankingListEnum.CHARM.instance.getEntry(0);
		if (top != null) {
			topPlayerId = top.getPlayerId();
			getTopPlayer(); // cache
		} else {
			topPlayerId = 0L;
		}
		LOG.info("[ACTCHARMTOP RELOAD]PRE[{}]NOW[{}]", old, topPlayerId);
		return old;
	}
	
	public DropGroup getCongratulationRewardDropGroup() {
		if (congratulationRewardDropGroup != null) {
			return congratulationRewardDropGroup;
		}
		DropGroupTemplate dropGroup = App.getApp().getServiceManager().get(TemplateService.class).get(DropGroupTemplate.class, CONGRATULATION_REWARD_DROP_GROUP_ID);
		DropGroup drop = dropGroup.getDrop();
		congratulationRewardDropGroup = drop;
		return drop;
	}
	
	private int getLeftCongratulationTimes(Player player) {
		if (player.getId() == topPlayerId) { // 不能祝贺自己
			return 0;
		}
		int lastDay = player.getPool().getIntValue(PlayerPool.PROPERTY_ACTIVITY_LAST_CONGRATULATION_CHARM_TOP_PLAYER_DAY);
		if (lastDay != TimeUpdater.getInstance().today() && TimeUpdater.getInstance().now() >= updateCongratulationNumTime) {
			player.poolSet(PlayerPool.PROPERTY_ACTIVITY_LAST_CONGRATULATION_CHARM_TOP_PLAYER_DAY, TimeUpdater.getInstance().today());
			player.poolSet(PlayerPool.PROPERTY_ACTIVITY_CONGRATULATION_TIMES, 0);
			return MAX_CONGRATULATION_TIMES_PER_DAY;
		}
		int n = MAX_CONGRATULATION_TIMES_PER_DAY - player.getPool().getIntValue(PlayerPool.PROPERTY_ACTIVITY_CONGRATULATION_TIMES);
		return n > 0 ? n : 0;
	}
	
	private static void addCongratulationTimes(Player player) {
		player.poolAdd(PlayerPool.PROPERTY_ACTIVITY_CONGRATULATION_TIMES, 1);
	}

}
